import React, {
  useContext,
  useEffect,
  isValidElement,
  cloneElement,
  useState,
  useMemo,
} from 'react'
import FormContext from '../Store/FormStore'
import Label from './label'
import Message from './message'

const FormItem = ({
  name,
  children,
  label,
  height = 50,
  labelWidth,
  required = false,
  rules = {},
  trigger = 'onChange',
  validateTrigger = 'onChange',
}) => {
  // 获取到表单实例下的api\方法
  const formInstance = useContext(FormContext)
  //
  const { registerValidateFields, dispatch, unRegisterValidate } = formInstance
  // 更新调度的方法
  const [, forceUpdate] = useState({})

  // 监听当前的store是否发生了改变
  const onStoreChange = useMemo(() => {
    /* 管理层改变 => 通知表单项 */
    const onStoreChange = {
      changeValue() {
        forceUpdate({})
      },
    }
    return onStoreChange
  }, [formInstance])

  // 当 onStoreChange 发生改变的时候执行 useEffect 生命周期
  useEffect(() => {
    // 注册表单 把表单的更新函数 传入到 FormStore 上
    name && registerValidateFields(name, onStoreChange, { ...rules, required })

    return () => {
      // 卸载表单
      name && unRegisterValidate(name)
    }
  }, [onStoreChange])

  // 可控表单： onChange 的时候 触发组件更新
  const getControlled = (child) => {
    const mergeChildrenProps = { ...child.props }
    console.log('mergeChildrenProps ===> ', mergeChildrenProps)
    // 如果没有name 直接返回props
    if (!name) return mergeChildrenProps

    /* 改变表单单元项的值 */
    const handleChange = (e) => {
      const value = e.target.value
      /* 设置表单的值 */
      dispatch({ type: 'setFieldsValue' }, name, value)
    }
    // 向控件中注入监听值变化的方法: trigger 也就是触发时机
    mergeChildrenProps[trigger] = handleChange
    // 设置完以后及逆行验证
    if (required || rules) {
      /* 验证表单单元项的值 */
      mergeChildrenProps[validateTrigger] = (e) => {
        // 当改变值和验证表单用统一事件时
        if (validateTrigger === trigger) {
          // 设置表单的值
          handleChange(e)
        }
        // 触发表单验证 更新渲染视图
        dispatch({ type: 'validateFieldValue' }, name)
      }
    }
    /* 获取 value */
    mergeChildrenProps.value = dispatch({ type: 'getFieldValue' }, name) || ''
    return mergeChildrenProps
  }

  let renderChildren
  if (isValidElement(children)) {
    // 获取 | 合并 ｜ 转发 | =>  props  将处理好的props传入到组件中 完成可控
    renderChildren = cloneElement(children, getControlled(children))
  } else {
    renderChildren = children
  }

  return (
    <Label
      height={height}
      label={label}
      labelWidth={labelWidth}
      required={required}
    >
      {renderChildren}
      <Message name={name} {...dispatch({ type: 'getFieldModel' }, name)} />
    </Label>
  )
}

export default FormItem
